package org.summerframework.core.jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.summerframework.core.util.SpringContextUtil;
import org.summerframework.core.util.UrlUtil;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 石超
 * @version v1.0.0
 */
public class JsonFullFileSerializer extends StdSerializer<Object> implements ContextualSerializer {
    private String endPath = "";
    private Class<?> handledType = Object.class;

    private JsonFullFile jsonFullFile;

    private DownloadUrlService downloadUrlService;

    public JsonFullFileSerializer() {
        super(Object.class, false);
    }

    public DownloadUrlService getDownloadUrlService() {
        if (downloadUrlService == null) {
            downloadUrlService = SpringContextUtil.getBean(DownloadUrlService.class);
        }

        return downloadUrlService;
    }

    public JsonFullFileSerializer(Class<?> t, JsonFullFile jsonFullFile) {
        super(t, false);
        this.handledType = t;
        this.jsonFullFile = jsonFullFile;
        if (jsonFullFile != null && StringUtils.isNotBlank(jsonFullFile.value())) {
            if (jsonFullFile.value().startsWith("/")) {
                this.endPath = jsonFullFile.value();
            } else {
                this.endPath = "/" + jsonFullFile.value();
            }
        }
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == null) {
            gen.writeNull();
        } else if (handledType.isAssignableFrom(Long.class)) {
            gen.writeNumber((Long) value);
        } else {
            gen.writeString(value.toString());
        }

        String key = gen.getOutputContext().getCurrentName();

        if (key.lastIndexOf("Id") > -1) {
            key = key.substring(0, key.lastIndexOf("Id"));
        }

        String name = StringUtils.isNotBlank(jsonFullFile.name()) ? jsonFullFile.name() : "full" + firstCharacterUppercase(key);

        if (value != null) {
            final Object parse = parse(value, true);

            if (parse == null) {
                gen.writeNullField(name);
            } else if (parse instanceof List) {
                gen.writeObjectField(name, parse);
            } else {
                gen.writeStringField(name, parse.toString());
            }
        } else {
            gen.writeNullField(name);
        }
    }

    private Object parse(Object value, boolean flag) {
        DownloadUrlService downloadUrlService = getDownloadUrlService();
        if (value instanceof Long) {
            value = downloadUrlService != null ? downloadUrlService.getUrl((Long) value) : UrlUtil.getUrl("default") + "/storage/" + value + endPath;
        } else if (value instanceof String) {
            if (StringUtils.isNotEmpty(jsonFullFile.separator()) && flag) {
                value = parse(StringUtils.split((String) value, jsonFullFile.separator()), false);
            } else if (StringUtils.isNotEmpty(jsonFullFile.separator()) && jsonFullFile.type() == Long.class) {
                value = downloadUrlService != null ? downloadUrlService.getUrl(Long.parseLong((String) value)) : UrlUtil.getUrl("default") + "/storage/" + value + endPath;
            } else {
                value = downloadUrlService != null ? downloadUrlService.getUrl((String) value) : UrlUtil.getUrl("default") + value + endPath;
            }
        } else if (value instanceof List) {
            List<Object> temp = new ArrayList<>();
            List<?> list = (List<?>) value;
            for (Object obj : list) {
                temp.add(parse(obj, false));
            }

            value = temp;
        } else if (value instanceof Object[]) {
            List<Object> temp = new ArrayList<>();
            Object[] list = (Object[]) value;
            for (Object obj : list) {
                temp.add(parse(obj, false));
            }

            value = temp;
        }

        return value;
    }

    private String firstCharacterUppercase(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) { // 为空直接跳过
            if (beanProperty.getType().isTypeOrSubTypeOf(Long.class) || beanProperty.getType().isTypeOrSubTypeOf(String.class)) {
                JsonFullFile annotation = beanProperty.getAnnotation(JsonFullFile.class);
                if (annotation == null) {
                    annotation = beanProperty.getContextAnnotation(JsonFullFile.class);
                }
                if (annotation != null) { // 如果能得到注解，就将注解的 value 传入 ImageURLSerialize
                    return new JsonFullFileSerializer(beanProperty.getType().getRawClass(), annotation);
                }
            }

            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }

        return serializerProvider.findNullValueSerializer(beanProperty);
    }
}
